package org.osite.xml;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.w3c.dom.Element;

public class ParseUtil {
  private static Pattern UPCASE_PAT = Pattern.compile("[A-Z]");

  private ParseUtil() {
  }

  public static <T> T newInstance(Class<T> type)
      throws PasreReflectionException {
    try {
      return newInstance(type.getDeclaredConstructor());
    } catch (NoSuchMethodException e) {
      throw new PasreReflectionException("cannot create instance: " + type, e);
    }
  }

  public static <T> T newInstance(Constructor<T> ctor, Object... arguments)
      throws PasreReflectionException {
    try {
      if (!ctor.isAccessible()) {
        ctor.setAccessible(true);
      }
      return ctor.newInstance(arguments);
    } catch (InstantiationException e) {
      throw new PasreReflectionException(
          "cannot create instance: " + ctor.getDeclaringClass(), e);
    } catch (IllegalAccessException e) {
      throw new PasreReflectionException(
          "cannot create instance: " + ctor.getDeclaringClass(), e);
    } catch (IllegalArgumentException e) {
      throw new PasreReflectionException(
          "cannot create instance: " + ctor.getDeclaringClass(), e);
    } catch (InvocationTargetException e) {
      throw new PasreReflectionException(
          "cannot create instance: " + ctor.getDeclaringClass(), e);
    } catch (SecurityException e) {
      throw new PasreReflectionException(
          "cannot create instance: " + ctor.getDeclaringClass(), e);
    }
  }

  public static <T extends AccessibleObject> T checkAccessibility(
      T object) throws ParseSetupException {
    try {
      if (!object.isAccessible()) {
        object.setAccessible(true);
      }
      return object;
    } catch (SecurityException e) {
      throw new ParseSetupException("cannot access: " + object, e);
    }
  }

  public static String toXmlConvention(String name) {
    Matcher matcher = UPCASE_PAT.matcher(name);
    StringBuffer buffer = new StringBuffer();
    while (matcher.find()) {
      matcher.appendReplacement(buffer, "");
      if (buffer.length() != 0) {
        buffer.append('-');
      }
      buffer.append(Character.toLowerCase(matcher.group(0).charAt(0)));
    }
    matcher.appendTail(buffer);

    return buffer.toString();
  }

  public static Element getComponentElement(Element element)
      throws XmlParseException {
    if ("cell".equals(element.getTagName())) {
      Element component = XmlUtil.getFirstElement(element);
      if (component == null) {
        throw new XmlParseException(
            "cannot find component in " + element);
      }
      return component;
    }
    return element;
  }
}
